
package com.ksvip.next.components.datasecure.logback;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.PatternLayout;
import ch.qos.logback.classic.pattern.EnsureExceptionHandling;
import ch.qos.logback.classic.pattern.ExtendedThrowableProxyConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Context;
import ch.qos.logback.core.pattern.Converter;
import ch.qos.logback.core.pattern.ConverterUtil;
import ch.qos.logback.core.pattern.PatternLayoutEncoderBase;

/**
 * 用于支持输出异常堆栈的时候，也能正常过滤敏感信息
 *
 * @author chenyao
 * @since 2019年5月15日 上午10:25:14
 * @see ch.qos.logback.classic.encoder.PatternLayoutEncoder
 */
public class SensitiveDataPatternLayoutEncoder extends PatternLayoutEncoderBase<ILoggingEvent> {
    @Override
    public void start() {
        PatternLayout patternLayout = new PatternLayout();
        patternLayout.setContext(this.context);
        patternLayout.setPattern(this.getPattern());
        patternLayout.setOutputPatternAsHeader(this.outputPatternAsHeader);
        patternLayout.setPostCompileProcessor(new EnsureExceptionHandling() {
            @Override
            public void process(Context context, Converter<ILoggingEvent> head) {
                if (head == null) {
                    // this should never happen
                    throw new IllegalArgumentException("cannot process empty chain");
                }
                if (!this.chainHandlesThrowable(head)) {
                    Converter<ILoggingEvent> tail = ConverterUtil.findTail(head);
                    Converter<ILoggingEvent> exConverter = null;
                    LoggerContext loggerContext = (LoggerContext) context;
                    if (loggerContext.isPackagingDataEnabled()) {
                        exConverter = new ExtendedThrowableProxyConverter();
                    } else {
                        exConverter = new SensitiveDataThrowableProxyConverter();
                    }
                    tail.setNext(exConverter);
                }
            }
        });
        patternLayout.start();
        this.layout = patternLayout;
        super.start();
    }
}
